package com.zlyx.easy.core.refresh;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.Order;

import com.zlyx.easy.core.annotations.SpringBean;
import com.zlyx.easy.core.loggers.Logger;
import com.zlyx.easy.core.refresh.annotations.RefreshBean;
import com.zlyx.easy.core.spring.SpringUtils;

/**
 * Spring系统事件工厂
 * 
 * @Auth 赵光
 * @Desc
 * @2018年12月12日 下午5:12:03
 */
@SpringBean(todo = { "Spring系统事件工厂" })
public class ApplicationEventFactory implements ApplicationListener<ApplicationEvent> {

	private boolean ClassPathChangedEventStatus = Boolean.TRUE;

	private boolean ContextRefreshedEventStatus = Boolean.TRUE;

	@Override
	public void onApplicationEvent(ApplicationEvent event) {
		try {
			String eventName = event.getClass().getSimpleName();
			if ("ClassPathChangedEvent".equals(eventName) && ClassPathChangedEventStatus) {
				ClassPathChangedEventStatus = Boolean.FALSE;
				doClassPathChangedEvent();
			} else if ("ContextRefreshedEvent".equals(eventName) && ContextRefreshedEventStatus) {
				ContextRefreshedEventStatus = Boolean.FALSE;
				doContextRefreshedEvent();
			}
		} catch (Exception e) {
			Logger.err(ApplicationEvent.class, e);
		}
	}

	/**
	 * 处理上下文刷新事件
	 * 
	 * @throws Exception
	 */
	private void doContextRefreshedEvent() {
		Map<String, IHandlerOnRefreshed> beansMap = SpringUtils.getBeansOfType(IHandlerOnRefreshed.class);
		if (beansMap != null && !beansMap.isEmpty()) {
			ApplicationContext context = SpringUtils.getApplicationContext();
			if (beansMap != null && !beansMap.isEmpty()) {
				List<IHandlerOnRefreshed> beans = new ArrayList<>(beansMap.values());
				IHandlerOnRefreshed handler = null;
				RefreshBean refreshAnnotation = null;
				Order orderAnnotation = null;
				int o = 5;
				for (int order = 0; order <= 10; order++) {
					for (int i = 0; i < beans.size(); i++) {
						try {
							handler = beans.get(i);
							orderAnnotation = AnnotationUtils.findAnnotation(handler.getClass(), Order.class);
							refreshAnnotation = handler.getClass().getAnnotation(RefreshBean.class);
							if (refreshAnnotation != null) {
								o = refreshAnnotation.order();
							} else if (orderAnnotation != null) {
								o = orderAnnotation.value();
							}
							if (refreshAnnotation == null || order == 5 || o <= order) {
								handler.doOnRefreshed(context);
								beans.remove(i);
							}
						} catch (Exception e) {
							Logger.err(handler.getClass(), e);
							beans.remove(i);
						}
					}
				}
			}
		}
	}

	/**
	 * 处理热加载事件
	 * 
	 * @throws Exception
	 */
	private void doClassPathChangedEvent() {
		Map<String, IHandlerOnChanged> beans = SpringUtils.getBeansOfType(IHandlerOnChanged.class);
		ApplicationContext context = SpringUtils.getApplicationContext();
		if (beans != null) {
			for (Entry<String, IHandlerOnChanged> handler : beans.entrySet()) {
				try {
					handler.getValue().doOnChanged(context);
				} catch (Exception e) {
					Logger.err(e);
				}
			}
		}
	}
}
